<?php defined('SYSPATH') or die('No direct access allowed.');

class Model_User extends ORM {
    
    const ROLE_CREATOR = 'creator';
    const ROLE_ADMIN   = 'admin';
    const ROLE_USER    = 'user';
    
    const INVITE_STATUS_NOT_SEND = 'not_send';
    const INVITE_STATUS_PENDING  = 'pending';
    const INVITE_STATUS_READY    = 'ready';
    
    const STATUS_ACTIVE  = 'active';
    const STATUS_DELETED = 'deleted';
    
    const NOTIFICATION_NEW_TICKET   = 1;
    const NOTIFICATION_ASSIGNED     = 2;
    const NOTIFICATION_NEW_REPLY    = 3;    
    
    public static function get_all_roles()
    {
        return array(
            self::ROLE_CREATOR => 'Владелец аккаунта',
            self::ROLE_ADMIN   => 'Администратор',
            self::ROLE_USER    => 'Пользователь',
        );
    }
    
    public static function get_available_roles()
    {
        return array(
            self::ROLE_USER    => 'Пользователь',
            self::ROLE_ADMIN   => 'Администратор',
        );
    }
    
    public static function get_all_invite_statuses()
    {
        return array(
            self::INVITE_STATUS_NOT_SEND => 'Инвайт не отослан',
            self::INVITE_STATUS_PENDING  => 'В ожидании',
            self::INVITE_STATUS_READY    => 'Успешная регистрация',
        );
    }
    
    public static function get_all_notifications()
    {
        return array(
            self::NOTIFICATION_NEW_TICKET,
            self::NOTIFICATION_ASSIGNED,
            self::NOTIFICATION_NEW_REPLY,
        );
    }
    
    public function filter($id)
    {
        $company = ORM::factory('company')->get_current();
        if (!$company->loaded()) {
            throw new HTTP_Exception_404('Нет такой компании');   
        }
        
        if (is_array($id)) {
            foreach ($id as $column => $value)
            {
                // Passing an array of column => values
                $this->where($column, '=', $value);
            }

            $this->find();
        } else {
            // Passing the primary key
            $this->where($this->_object_name.'.'.$this->_primary_key, '=', $id)->find();
        }
        
        if (!$this->loaded()) {
            throw new HTTP_Exception_404('Запись не найдена');   
        }
        
        if ($company->id != $this->company_id) {
            throw new HTTP_Exception_404('Такого пользователя нет'); 
        }
        
        return $this;    
    }
    
    public static function check_role($needed_role)
    {
        $roles = array(
            self::ROLE_CREATOR => 2,
            self::ROLE_ADMIN   => 1,
            self::ROLE_USER    => 0,
        );
        
        $current_user = Model_Auth::instance()->get_user();
        if ($roles[$current_user->role] >= $roles[$needed_role]) {
            return true;    
        }
        return false;
    }
    
    public static function check_role_by_user(Model_User $user)
    {
        $current_user = Model_Auth::instance()->get_user();
        if ($current_user->company_id != $user->company_id) {
            return false;
        }
        if ($current_user->role == Model_User::ROLE_USER && $user->role == Model_User::ROLE_USER && $current_user->id != $user->id) {
            return false;    
        }
        
        return self::check_role($user->role);   
    }
    
    public static function check_email($email)
    {
        $user = ORM::factory('user')
                    ->where('email', '=', $email)
                    ->find();
        if ($user->loaded() && $user->company_id && $user->name && $user->password) {
            return false;    
        }
        return true;
    }

	/**
	 * Complete the login for a user by incrementing the logins and saving login timestamp
	 *
	 * @return void
	 */
	public function complete_login()
	{
		if ($this->_loaded) {
			// Update the number of logins
			$this->logins = new Database_Expression('logins + 1');

			// Set the last login date
			$this->last_login = time();

			// Save the user
			$this->update();
		}
	}
    
    public function get_users(Model_Company $company) 
    {
        $users = $this->_get_users_query()
                    ->where('company_id', '=', $company->id)
                    ->find_all()
                    ->as_array();  
        return $users;
    }
    
    public function get_users_by_list($list)
    {
        $ids = $users = array();
        foreach ($list as $item) {
            $ids[$item->user_id] = $item->user_id;
            if ($item instanceof Model_Log && $item->type == 'assigned') {
                $ids[$item->value] = $item->value;    
            }    
        }
        if (count($ids)) {
            $_users = $this->_get_users_query()
                        ->where('id', 'IN', $ids)
                        ->find_all()
                        ->as_array();
            foreach ($_users as $user) {
                $users[$user->id] = $user;    
            }                
        }
        return $users;
    }
    
    public function get_all_users($delete_current = false)
    {
        $company = ORM::factory('company')->get_current();  
        $current_user = Model_Auth::instance()->get_user();
        
        $users = array();
        $_users = $this->_get_users_query()
                        ->where('company_id', '=', $company->id)
                        ->find_all()
                        ->as_array();
        foreach ($_users as $user) {
            $users[$user->id] = $user;   
        }
                        
        return $users;   
    }
    
    public function get_user_by_invite($invite)
    {
        $user = $this->_get_users_query()
                    ->where('invite', '=', $invite)
                    ->find();
        if (!$user->loaded()) {
            throw new Model_Exception('Такого пользователя нет');      
        }
        return $user;
    }
    
    public function get_user_by_email($email)
    {
        $user = $this->_get_users_query()
                    ->where('email', '=', $email)
                    ->find();
        //if (!$user->loaded()) {
            //throw new Model_Exception('Такого пользователя нет');      
        //}
        return $user;
    }
    
    protected function _get_users_query()
    {
        return ORM::factory('user')
                    ->where('status', '=', self::STATUS_ACTIVE);
    }
    
    /**
     * Добавление пользователя
     * 
     * @param   string   email
     * @param   string   password
     * @return  Model_User
     */
    public function add_user(Model_Company $company, $email, $name, $password)
    {
        /* TODO validation */
        
        $ref = '';
        if (isset($_COOKIE['ref']) && $_COOKIE['ref']) {
            $ref = $_COOKIE['ref'];
        }
        
        $email    = Security::xss_clean($email);
        $name     = Security::xss_clean($name);
        
        try {
            $this->company_id = $company->id;
            $this->email      = $email;
            $this->name       = $name;   
            $this->password   = Model_Auth::instance()->hash_password($password);
            $this->ref_code   = $this->generate_password();
            $this->from_ref_code = $ref;
            $this->created_at = time();  
            $this->save();
        } catch (Database_Exception $e) {
            if (strstr($e->getMessage(), 'Duplicate entry') !== false) {
                $user = ORM::factory('user')
                            ->where('email', '=', $email)
                            ->find();
                if ($user->loaded() && !$user->company_id && !$user->name && !$user->password) {
                    $user->company_id = $company->id;
                    $user->name       = $name;   
                    $user->password   = Model_Auth::instance()->hash_password($password); 
                    $user->save();
                    
                    return $user;
                }
                throw new Model_Exception('Такой пользователь уже зарегистрирован');
            } else {
                throw new Model_Exception($e->getMessage());
            }
        }
        
        return $this;
    }
    
    public function add_user_by_invite($email, $name, $role, $send_invite)
    {
        /* TODO validation */
        
        $company = ORM::factory('company')->get_current();
        if (!$company->loaded()) {
            throw new Model_Exception('Неизвестная компания');   
        }
        
        if (!array_key_exists($role, self::get_available_roles())) {
            throw new Model_Exception('Некорректная роль');    
        }
        
        $email    = Security::xss_clean($email);
        $name     = Security::xss_clean($name);
        
        try {
            $this->company_id = $company->id;
            $this->email      = $email;
            $this->name       = $name;   
            $this->password   = '';
            $this->role       = $role;
            $this->ref_code   = $this->generate_password(); 
            $this->created_at = time();
            $this->save();
        } catch (Database_Exception $e) {
            if (strstr($e->getMessage(), 'Duplicate entry') !== false) {
                throw new Model_Exception('Такой пользователь уже зарегистрирован');
            } else {
                throw new Model_Exception($e->getMessage());
            }
        }
        
        if ($send_invite) {
            $this->send_invite();    
        } 
        
        return $this;
    }
    
    public function add_user_for_ref_system($email)
    {
        /* TODO validation */
        
        $user = ORM::factory('user')
                    ->where('email', '=', $email)
                    ->find();
        if ($user->loaded()) {
            return $user;    
        }
        
        $ref = '';
        if (isset($_COOKIE['ref']) && $_COOKIE['ref']) {
            $ref = $_COOKIE['ref'];
        }
        
        $email    = Security::xss_clean($email);
        
        $this->company_id = 0;
        $this->email      = $email;
        $this->name       = '';   
        $this->password   = '';
        $this->ref_code   = $this->generate_password();
        $this->from_ref_code = $ref; 
        $this->created_at = time(); 
        $this->save();
        
        return $this;
    }
    
    /**
    * put your comment there...
    * 
    * @param mixed $email
    * @param mixed $password
    */
    public function edit_user($email, $name, $role = null, $password = null)
    {
        $company = ORM::factory('company')->get_current();
        if (!$company->loaded()) {
            throw new Model_Exception('Неизвестная компания');   
        }
        
        if ($role && !array_key_exists($role, self::get_available_roles())) {
            throw new Model_Exception('Некорректная роль');    
        }
        
        $email    = Security::xss_clean($email);
        $name     = Security::xss_clean($name);
        
        $this->email    = $email;
        $this->name     = $name;
        if ($role) {
            $this->role = $role;   
        }   
        if ($password) {
            $this->password = Model_Auth::instance()->hash_password($password);;
        }   
        $this->save();
        
        return $this;
    }
    
    public function edit_user_by_invite($email, $name, $password = null)
    {
        $this->invite_status = self::INVITE_STATUS_READY;
        
        $email    = Security::xss_clean($email);
        $name     = Security::xss_clean($name);
        
        $this->edit_user($email, $name, null, $password);
        return $this;    
    }
    
    /**
     * put your comment there...
     * 
     */
    public function in_company(Model_Company $company, $role = null)
    {
        if ($company->id == $this->company_id) {
            return true;    
        }
        return false;
        
        /*$user_shop = ORM::factory('User_Shop')
                            ->where('user_id', '=', $this->id)
                            ->and_where('shop_id', '=', $shop->id)
                            ->find();

        if ($user_shop->loaded()) {
            if (!$role) {
                return true;
            }
            
            if ($role == $user_shop->role) {
                return true;
            }
        } 
        
        return false; */
    }
    
    public function send_invite($auto_save = true)
    {
        $this->invite        = $this->generate_password(16);
        $this->invite_status = self::INVITE_STATUS_PENDING;
        if ($auto_save) {
            $this->save();   
        } 
        
        Model_Mailer::invite_user($this);  
    }
    
    public function mark_user_as_deleted()
    {
        DB::update('tickets')
                ->set(array('assigned_id' => 0))
                ->where('assigned_id', '=', $this->id)
                ->execute();
        
        $this->email = 'deleted_'.$this->email;
        $this->status = self::STATUS_DELETED;
        $this->save();   
    }
    
    public function generate_password($length = 10)
    {
        $arr = array('a','b','c','d','e','f',
                 'g','h','i','j','k','l',
                 'm','n','o','p','r','s',
                 't','u','v','x','y','z',
                 'A','B','C','D','E','F',
                 'G','H','I','J','K','L',
                 'M','N','O','P','R','S',
                 'T','U','V','X','Y','Z',
                 '1','2','3','4','5','6',
                 '7','8','9','0',);
                 
        // Генерируем пароль
        $pass = '';
        for($i = 0; $i < $length; $i++) {
            // Вычисляем случайный индекс массива
            $index = rand(0, count($arr) - 1);
            $pass .= $arr[$index];
        }
        return $pass;
    }
    
    /**
     * установка флага
     * 
     */
    public function set_notifications($id_bit, $bit, $auto_save = true){
        if ($bit) {
            $bit=1;
        } else {
            $bit=0;
        }
        $str_bit=1<<$id_bit;
        if ($bit) {
            $this->notifications = $this->notifications|$str_bit;
        } else { 
            $str_bit=~$str_bit;
            $this->notifications = $this->notifications&$str_bit;
        }
        if ($auto_save) {
            $this->save();
        }
    }
    
    /**
     * Получение состояния флага
     * @param int $idBit Номер флага (0 - 31)
     */
    public function check_notifications($id_bit) {
        $get_bit = 1;
        $get_bit = $get_bit<<$id_bit;
        if (($this->notifications & $get_bit) == $get_bit) {
            return true;
        } else {
            return false;
        }
    }

	/**
	 * Password validation for plain passwords.
	 *
	 * @param array $values
	 * @return Validation
	 */
	/*public static function get_password_validation($values)
	{
		return Validation::factory($values)
			->rule('password', 'min_length', array(':value', 8))
			->rule('password_confirm', 'matches', array(':validation', ':field', 'password'));
	}  */

}